package com.demo.netty.tomcat;


import com.demo.rule.servlet.MyServlet;
import com.demo.tomcat.MyRequest;
import com.demo.tomcat.MyResponse;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.http.HttpRequest;
import io.netty.handler.codec.http.HttpRequestDecoder;
import io.netty.handler.codec.http.HttpResponseEncoder;

import java.io.FileInputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

public class MyNettyTomcat {


    private int port = 8090;
    private ServerSocket serverSocket;

    private Map<String, MyNettyServlet> map = new HashMap<>();

    private Properties xmlWeb = new Properties();


    public static void main(String[] args) {
        new MyNettyTomcat().start();
    }

    private void init() {
        try {
            String web_inf = this.getClass().getResource("/").getPath();
            FileInputStream inputStream = new FileInputStream(web_inf + "web.properties");
            xmlWeb.load(inputStream);
            //
            for (Object k : xmlWeb.keySet()) {
                String key = k.toString();
                if (key.endsWith(".url")) {
                    String servletName = key.replaceAll("\\.url", "");
                    String url = xmlWeb.getProperty(key);
                    String className = xmlWeb.getProperty(servletName + ".className");
                    //单实例 多线程
                    Class<?> aClass = this.getClass().getClassLoader().loadClass(className);
                    MyNettyServlet servlet = (MyNettyServlet) aClass.newInstance();
                    map.put(url, servlet);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void start() {
        //加载配置文件
        init();
        NioEventLoopGroup boss = new NioEventLoopGroup();
        NioEventLoopGroup worker = new NioEventLoopGroup();
        try {

            ServerBootstrap serverBootstrap = new ServerBootstrap();
            serverBootstrap.group(boss, worker)
                    .channel(NioServerSocketChannel.class)
                    .childHandler(new ChannelInitializer<NioSocketChannel>() {
                        @Override
                        protected void initChannel(NioSocketChannel nioServerSocketChannel) throws Exception {
                            nioServerSocketChannel.pipeline().addLast(new HttpResponseEncoder());
                            nioServerSocketChannel.pipeline().addLast(new HttpRequestDecoder());
                            nioServerSocketChannel.pipeline().addLast(new MyTomcatHandler());
                        }
                    })
                    .option(ChannelOption.SO_BACKLOG, 128)
                    .childOption(ChannelOption.SO_KEEPALIVE, true);
            ChannelFuture sync = serverBootstrap.bind(8090).sync();
            sync.channel().closeFuture().sync();

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            boss.shutdownGracefully();
            worker.shutdownGracefully();
        }
    }

    public class MyTomcatHandler extends ChannelInboundHandlerAdapter {

        @Override
        public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {

            if (msg instanceof HttpRequest) {
                HttpRequest req = (HttpRequest) msg;
                MyNettyRequest request = new MyNettyRequest(ctx, req);
                MyNettyResponse myNettyResponse = new MyNettyResponse(ctx, req);
                String url = request.getUrl();
                if (map.containsKey(url)) {
                    map.get(url).service(request, myNettyResponse);
                }
            }


        }
    }

}
